/*************************************************************************
	Support alignment, trimmed image and back layer(for trans)

*************************************************************************/

using UnityEngine;
using System;

//[RequireComponent(typeof(MeshCollider))]
[RequireComponent(typeof(MeshFilter))]
[RequireComponent(typeof(MeshRenderer))]
public class UKagLayer : UTVPAnimationLayer {
	
	protected UKagLayer m_BackLayer = null;
	protected bool m_IsBack = false;
	public bool BackVisible = false;

	// Trans
	public enum TRANS_TYPE
	{
		NONE,
		CROSSFADE,
		UNIVERSAL // use “rule” image
	}
	private TRANS_TYPE m_TransType = TRANS_TYPE.NONE;
	public TRANS_TYPE TransType { get { return m_TransType; } }
	protected float m_TransTime = 0;
	protected float m_TransBeginTime = 0;
	private float m_ProportionStart = 0;
	private float m_ProportionEnd = 0;
	private Material m_MaterialTrans = null;
	
	protected internal void SetBackLayer(UKagLayer backLayer)
	{
		m_BackLayer = backLayer;
		m_BackLayer.Visible = false;
		m_BackLayer.AbsoluteIndex = AbsoluteIndex - 10;
		m_BackLayer.m_IsBack = true;
	}
	
	public UKagLayer BackLayer { get { return m_BackLayer; } }
	
	public UTVPImage ImageBack
	{
		get { return m_BackLayer.Image; }
		set
		{
			if (value == null)
				value = UTVPStorages.transparencyImage;
			
			m_BackLayer.Image = value;
		}
	}
	
	public override int AbsoluteIndex
	{
		get { return base.AbsoluteIndex; }
		set
		{
			base.AbsoluteIndex = value;
			if (m_BackLayer != null)
				m_BackLayer.AbsoluteIndex = value - 10;
		}
	}
	
	public override bool UseSharedMaterial
	{
		get { return base.UseSharedMaterial; }
		set
		{
			base.UseSharedMaterial = value;
			if (m_BackLayer != null)
				m_BackLayer.UseSharedMaterial = value;
		}
	}
	public override Color MaterialColor
	{
		get { return base.MaterialColor; }
		set
		{;
			base.MaterialColor = value;
			if (m_BackLayer != null)
				m_BackLayer.MaterialColor = value;
		}
	}
	
	protected override void ResetMaterial()
	{
		base.ResetMaterial();
		if (m_MaterialTrans == null)
		{
			m_MaterialTrans = new Material(m_Storages.shaderTrans);
			m_MaterialTrans.name = this.name + "_Trans";
		}
	}
	
	// vague: [0, 4]
	public void BeginTransition(TRANS_TYPE transType, float time, UTVPImage rule, float vague)
	{
		if (m_BackLayer == null)
			return;
		if (BackLayer.Image.tex != UTVPStorages.transparencyImage.tex)
		{
			SetPosAndSize(BackLayer.Left, BackLayer.Top, BackLayer.Width, BackLayer.Height);
			SetImageSize(Image.tex.width, Image.tex.height);
			RefreshPosAndSize_impl();
		}
		BeginTransition_impl(transType, time, rule, vague);
		//if (BackVisible)
		//{
		//	m_BackLayer.visible = true;
		//	m_BackLayer.beginTransition_impl(transType, time, rule, vague);
		//}
	}
	private void BeginTransition_impl(TRANS_TYPE transType, float time, UTVPImage rule, float vague)
	{
		m_TransType = transType;
		m_TransTime = time;
		m_TransBeginTime = Time.time;
		
		m_MeshRenderer.enabled = true;
		m_MaterialTrans.SetTexture("_MainTex", m_Image.tex);
		if (BackVisible)
			m_MaterialTrans.SetTexture("_BackTex", m_BackLayer.Image.tex);
		else
			m_MaterialTrans.SetTexture("_BackTex", UTVPStorages.transparencyImage.tex);
		switch (transType)
		{
		case TRANS_TYPE.UNIVERSAL:
			m_ProportionStart = 1.0f;
			m_ProportionEnd = -1.0f;
			m_MaterialTrans.SetTexture("_RuleTex", rule.tex);
			m_MaterialTrans.SetFloat("_Vague", Mathf.Pow(2.0f, vague) / 16.0f);
			m_MaterialTrans.SetFloat("_Proportion", m_ProportionStart);
			m_MeshRenderer.sharedMaterial = m_MaterialTrans;
			break;
		case TRANS_TYPE.CROSSFADE:
		default:
			m_ProportionStart = 1.0f;
			m_ProportionEnd = 0.0f;
			m_MaterialTrans.SetTexture("_RuleTex", UTVPStorages.transparencyImage.tex);
			m_MaterialTrans.SetFloat("_Vague", 0.0625f);
			m_MaterialTrans.SetFloat("_Proportion", m_ProportionStart);
			m_MeshRenderer.sharedMaterial = m_MaterialTrans;
			break;
		}
	}
	
	public virtual void StopTransition()
	{
		if (m_TransType == TRANS_TYPE.NONE)
			return;
		m_TransType = TRANS_TYPE.NONE;
		if (BackVisible)
		{
			AssignBack();
		}
		else
			Image = null;
	}

	protected override void OnTransitionCompleted()
	{
		UKagSystem system = (UKagSystem)m_System;
		system.conductor.Trigger("_trans");
		system.conductor.Trigger("_trans_" + name);
	}
	
	protected override void OnAnimationCompleted()
	{
		UKagSystem system = (UKagSystem)m_System;
		system.conductor.Trigger("_anim");
		system.conductor.Trigger("_anim_" + name);
	}
	
	// Update is called once per frame
	protected internal override void LayerUpdate ()
	{
		if (TransType != TRANS_TYPE.NONE)
		{
			float currTime = Time.time;
			m_MaterialTrans.SetFloat("_Proportion", Mathf.Lerp(m_ProportionStart, m_ProportionEnd ,(currTime - m_TransBeginTime) / m_TransTime));
			if(currTime - m_TransBeginTime >= m_TransTime)
			{
				StopTransition();
				OnTransitionCompleted();
			}
		}

		base.LayerUpdate();
	}
	
	public void SetLayerOptions(string left, string top, string width, string height,
		string imageLeft, string imageTop, string imageWidth, string imageHeight,
		string slice9Left, string slice9Top, string slice9Right, string slice9Bottom,
	    string flipLR, string flipUD, string localOrigin, string worldOrigin,
		string hitType, string hitThreshold, string index, string opacity, string visible)
	{
		if(Image == null)
			return;
		
		UKagSystem system = (UKagSystem)m_System;
		
		system.Str2Number(width, ref this.m_Width);
		system.Str2Number(height, ref this.m_Height);
		system.Str2Number(imageLeft, ref this.m_ImageLeft);
		system.Str2Number(imageTop, ref this.m_ImageTop);
		system.Str2Number(imageWidth, ref this.m_ImageWidth);
		system.Str2Number(imageHeight, ref this.m_ImageHeight);
		system.Str2Number(slice9Left, ref this.m_Slice9Left);
		system.Str2Number(slice9Top, ref this.m_Slice9Top);
		system.Str2Number(slice9Right, ref this.m_Slice9Right);
		system.Str2Number(slice9Bottom, ref this.m_Slice9Bottom);
		system.Str2Number(localOrigin, ref this.m_LocalOrigin);
		system.Str2Number(worldOrigin, ref this.m_WorldOrigin);

		int x = this.m_Left;
		int y = this.m_Top;
		system.Str2Number(left, ref x);
		system.Str2Number(top, ref y);
		SetPos(x, y);

		if (flipLR != null)
			m_FlipLR = system.Str2Bool(flipLR);
		if (flipUD != null)
			m_FlipUD = system.Str2Bool(flipUD);
		
		RefreshPosAndSize();
		
		if(hitType != null)
			this.m_HitType = (HIT_TYPE)Enum.Parse(typeof(HIT_TYPE), hitType.ToUpper());
		system.Str2Number(hitThreshold, ref this.m_HitThreshold);
		
		if (index != null)
		{
			int indexTemp = 0;
			system.Str2Number(index, ref indexTemp);
			AbsoluteIndex = indexTemp;
		}
		if (opacity != null)
		{
			int opacityTemp = 0;
			system.Str2Number(opacity, ref opacityTemp);
			this.Opacity = opacityTemp;
		}
		if (visible != null)
			this.Visible = visible == "true";
	}
	
	public void SetAnimOption(string animName, string animPause, string currFrameIdx)
	{
		if (!string.IsNullOrEmpty(animName))
			CurrAnimSequenceName = animName;
		if (animPause != null)
			this.AnimPause = animPause == "true";
		
		UKagSystem system = (UKagSystem)m_System;

		if (CurrAnimSequence == null)
			return;
		if (CurrAnimSequence.frames == null || CurrAnimSequence.frames.Length <= 1)
			this.AnimPause = true;
		
		if (currFrameIdx != null)
		{
			int currFrameIdxTemp = 0;
			system.Str2Number(currFrameIdx, ref currFrameIdxTemp);
			this.CurrFrameIdx = currFrameIdxTemp;
		}
	}
	
	public void LoadBackImage(UTVPImage image)
	{
		ImageBack = image;
		m_BackLayer.SetSizeToImageSize();
	}
	
	private void AssignBack()
	{
		SetPos(m_BackLayer.Left, m_BackLayer.Top);
		Assign(m_BackLayer);
	}
	
	protected override void AssignSelf(UTVPLayer src)
	{
		base.AssignSelf(src);
		if (src is UKagLayer)
		{
			UKagLayer srcTemp = (UKagLayer)src;
			if (m_BackLayer != null && srcTemp.m_BackLayer != null)
				m_BackLayer.Assign(srcTemp.m_BackLayer);
		}
	}
}